#include "IntelPubTrans.h"
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <cjson/cJSON.h>
#include <string.h>

// 定义经纬度结构体
typedef struct
{
    double latitude;
    double longitude;
} Location;

// 定义全局变量
char start_city[50];
char start_position[50];
char destination_city[50];
char destination_position[50];

// 解析json转化为字符串
void parse_json(const char *json_str) {
    cJSON *json = cJSON_Parse(json_str);
    if (json == NULL) {
        fprintf(stderr, "Error parsing JSON: %s\n", cJSON_GetErrorPtr());
        return;
    }

    cJSON *first_item = cJSON_GetArrayItem(json, 0);
    cJSON *second_item = cJSON_GetArrayItem(json, 1);

    // 初始化全局变量
    strncpy(start_city, cJSON_GetObjectItemCaseSensitive(first_item, "city")->valuestring, sizeof(start_city) - 1);
    strncpy(start_position, cJSON_GetObjectItemCaseSensitive(first_item, "position")->valuestring, sizeof(start_position) - 1);
    strncpy(destination_city, cJSON_GetObjectItemCaseSensitive(second_item, "city")->valuestring, sizeof(destination_city) - 1);
    strncpy(destination_position, cJSON_GetObjectItemCaseSensitive(second_item, "position")->valuestring, sizeof(destination_position) - 1);

    // 确保字符串以 null 结尾
    start_city[sizeof(start_city) - 1] = '\0';
    start_position[sizeof(start_position) - 1] = '\0';
    destination_city[sizeof(destination_city) - 1] = '\0';
    destination_position[sizeof(destination_position) - 1] = '\0';

    cJSON_Delete(json);
}

// 用于存储 CURL 响应的缓冲区
struct MemoryStruct {
    char *memory;
    size_t size;
};

static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;

    char *ptr = realloc(mem->memory, mem->size + realsize + 1);
    if (ptr == NULL) {
        // 内存分配失败
        return 0;
    }

    mem->memory = ptr;
    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;

    return realsize;
}

char* get_coordinates(const char *city, const char *position) {
    CURL *curl;
    CURLcode res;
    struct MemoryStruct chunk;

    chunk.memory = malloc(1);
    chunk.size = 0;

    char url[256];
    snprintf(url, sizeof(url), "https://restapi.amap.com/v3/geocode/geo?address=%s&city=%s&key=c6dc687285a376347d73993a80352ff0", position, city);

    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();

    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

        res = curl_easy_perform(curl);

        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
            free(chunk.memory);
            chunk.memory = NULL;
        }

        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();

    return chunk.memory;
}

char* extract_location(const char *json_response) {
    cJSON *json = cJSON_Parse(json_response);
    if (json == NULL) {
        fprintf(stderr, "Error parsing JSON: %s\n", cJSON_GetErrorPtr());
        return NULL;
    }

    cJSON *geocodes = cJSON_GetObjectItemCaseSensitive(json, "geocodes");
    if (!cJSON_IsArray(geocodes) || cJSON_GetArraySize(geocodes) == 0) {
        cJSON_Delete(json);
        return NULL;
    }

    cJSON *first_geocode = cJSON_GetArrayItem(geocodes, 0);
    cJSON *location = cJSON_GetObjectItemCaseSensitive(first_geocode, "location");
    if (!cJSON_IsString(location) || (location->valuestring == NULL)) {
        cJSON_Delete(json);
        return NULL;
    }

    char *location_str = strdup(location->valuestring);
    cJSON_Delete(json);
    return location_str;
}

cJSON *get_transit_route(const char *response, size_t size)
{
    cJSON *json = cJSON_ParseWithLength(response, size);
    if (json == NULL)
    {
        fprintf(stderr, "解析 JSON 失败: [%s]\n", cJSON_GetErrorPtr());
        return NULL;
    }

    cJSON *status = cJSON_GetObjectItemCaseSensitive(json, "status");
    if (!cJSON_IsString(status) || (status->valuestring == NULL) || strcmp(status->valuestring, "1") != 0)
    {
        fprintf(stderr, "API 返回错误\n");
        cJSON_Delete(json);
        return NULL;
    }

    cJSON *route = cJSON_GetObjectItemCaseSensitive(json, "route");
    if (!cJSON_IsObject(route))
    {
        fprintf(stderr, "JSON 格式错误: 找不到 'route' 对象\n");
        cJSON_Delete(json);
        return NULL;
    }

    cJSON *transits = cJSON_GetObjectItemCaseSensitive(route, "transits");
    if (!cJSON_IsArray(transits))
    {
        fprintf(stderr, "JSON 格式错误: 找不到 'transits' 数组\n");
        cJSON_Delete(json);
        return NULL;
    }

    cJSON *result_array = cJSON_CreateArray();

    cJSON *transit = NULL;
    int route_index = 1;
    cJSON_ArrayForEach(transit, transits)
    {
        if (!cJSON_IsObject(transit))
        {
            continue;
        }

        cJSON *route_obj = cJSON_CreateObject();
        cJSON_AddNumberToObject(route_obj, "route_number", route_index);
        cJSON_AddStringToObject(route_obj, "total_distance", cJSON_GetObjectItemCaseSensitive(transit, "distance")->valuestring);
        cJSON_AddStringToObject(route_obj, "total_walking_distance", cJSON_GetObjectItemCaseSensitive(transit, "walking_distance")->valuestring);

        cJSON *segments = cJSON_GetObjectItemCaseSensitive(transit, "segments");
        if (!cJSON_IsArray(segments))
        {
            printf("aaaaaa");
            continue;
        }

        cJSON *segments_array = cJSON_CreateArray();

        cJSON *segment = NULL;
        int segment_index = 1;
        cJSON_ArrayForEach(segment, segments)
        {
            if (!cJSON_IsObject(segment))
            {
                continue;
            }

            cJSON *segment_obj = cJSON_CreateObject();
            cJSON_AddNumberToObject(segment_obj, "segment_number", segment_index);

            cJSON *walking = cJSON_GetObjectItemCaseSensitive(segment, "walking");
            if (cJSON_IsObject(walking))
            {
                cJSON *walking_obj = cJSON_CreateObject();
                cJSON_AddStringToObject(walking_obj, "type", "walking");
                cJSON_AddNumberToObject(walking_obj, "distance", atoi(cJSON_GetObjectItemCaseSensitive(walking, "distance")->valuestring));

                cJSON *steps = cJSON_GetObjectItemCaseSensitive(walking, "steps");
                if (cJSON_IsArray(steps))
                {
                    cJSON *details_array = cJSON_CreateArray();
                    cJSON *step = NULL;
                    cJSON_ArrayForEach(step, steps)
                    {
                        if (cJSON_IsObject(step))
                        {
                            cJSON *instruction = cJSON_GetObjectItemCaseSensitive(step, "instruction");
                            if (cJSON_IsString(instruction))
                            {
                                cJSON_AddItemToArray(details_array, cJSON_CreateString(instruction->valuestring));
                            }
                        }
                    }
                    cJSON_AddItemToObject(walking_obj, "details", details_array);
                }

                cJSON_AddItemToObject(segment_obj, "walking", walking_obj);
            }

            cJSON *bus = cJSON_GetObjectItemCaseSensitive(segment, "bus");
            if (cJSON_IsObject(bus))
            {
                cJSON *buslines = cJSON_GetObjectItemCaseSensitive(bus, "buslines");
                if (cJSON_IsArray(buslines))
                {
                    cJSON *busline = cJSON_GetArrayItem(buslines, 0); // 假设只有一条公交线路
                    if (cJSON_IsObject(busline))
                    {
                        cJSON *bus_obj = cJSON_CreateObject();
                        cJSON_AddStringToObject(bus_obj, "type", "bus");
                        cJSON_AddStringToObject(bus_obj, "name", cJSON_GetObjectItemCaseSensitive(busline, "name")->valuestring);
                        cJSON_AddNumberToObject(bus_obj, "distance", atoi(cJSON_GetObjectItemCaseSensitive(busline, "distance")->valuestring));

                        cJSON *cost = cJSON_GetObjectItemCaseSensitive(busline, "cost");
                        cJSON *duration = cJSON_GetObjectItemCaseSensitive(cost, "duration");
                        int duration_in_seconds = atoi(duration->valuestring);
                        int minutes = duration_in_seconds / 60;
                        cJSON_AddNumberToObject(bus_obj, "duration_minutes", minutes);

                        cJSON *departure_stop = cJSON_GetObjectItemCaseSensitive(busline, "departure_stop");
                        cJSON *arrival_stop = cJSON_GetObjectItemCaseSensitive(busline, "arrival_stop");
                        cJSON_AddStringToObject(bus_obj, "departure_stop", cJSON_GetObjectItemCaseSensitive(departure_stop, "name")->valuestring);
                        cJSON_AddStringToObject(bus_obj, "arrival_stop", cJSON_GetObjectItemCaseSensitive(arrival_stop, "name")->valuestring);

                        cJSON *start_time = cJSON_GetObjectItemCaseSensitive(busline, "start_time");
                        cJSON *end_time = cJSON_GetObjectItemCaseSensitive(busline, "end_time");
                        char first_bus[6], last_bus[6];
                        snprintf(first_bus, sizeof(first_bus), "%.2s:%.2s", start_time->valuestring, start_time->valuestring + 2);
                        snprintf(last_bus, sizeof(last_bus), "%.2s:%.2s", end_time->valuestring, end_time->valuestring + 2);
                        cJSON_AddStringToObject(bus_obj, "first_bus", first_bus);
                        cJSON_AddStringToObject(bus_obj, "last_bus", last_bus);

                        cJSON *via_num = cJSON_GetObjectItemCaseSensitive(busline, "via_num");
                        cJSON_AddNumberToObject(bus_obj, "stops_count", atoi(via_num->valuestring));

                        cJSON *via_stops = cJSON_GetObjectItemCaseSensitive(busline, "via_stops");
                        if (cJSON_IsArray(via_stops))
                        {
                            cJSON *stops_array = cJSON_CreateArray();
                            cJSON *via_stop = NULL;
                            cJSON_ArrayForEach(via_stop, via_stops)
                            {
                                if (cJSON_IsObject(via_stop))
                                {
                                    cJSON *stop_name = cJSON_GetObjectItemCaseSensitive(via_stop, "name");
                                    if (cJSON_IsString(stop_name))
                                    {
                                        cJSON_AddItemToArray(stops_array, cJSON_CreateString(stop_name->valuestring));
                                    }
                                }
                            }
                            cJSON_AddItemToObject(bus_obj, "stops", stops_array);
                        }

                        cJSON_AddItemToObject(segment_obj, "bus", bus_obj);
                    }
                }
            }

            cJSON *taxi = cJSON_GetObjectItemCaseSensitive(segment, "taxi");
            if (cJSON_IsObject(taxi))
            {
                cJSON *taxi_obj = cJSON_CreateObject();
                cJSON_AddStringToObject(taxi_obj, "type", "taxi");
                cJSON_AddNumberToObject(taxi_obj, "price", atof(cJSON_GetObjectItemCaseSensitive(taxi, "price")->valuestring));
                cJSON_AddStringToObject(taxi_obj, "duration", cJSON_GetObjectItemCaseSensitive(taxi, "drivetime")->valuestring);
                cJSON_AddNumberToObject(taxi_obj, "distance", atoi(cJSON_GetObjectItemCaseSensitive(taxi, "distance")->valuestring));
                cJSON_AddStringToObject(taxi_obj, "start_point", cJSON_GetObjectItemCaseSensitive(taxi, "startname")->valuestring);
                cJSON_AddStringToObject(taxi_obj, "end_point", cJSON_GetObjectItemCaseSensitive(taxi, "endname")->valuestring);

                cJSON_AddItemToObject(segment_obj, "taxi", taxi_obj);
            }

            cJSON_AddItemToArray(segments_array, segment_obj);
            segment_index++;
        }

        cJSON_AddItemToObject(route_obj, "segments", segments_array);
        cJSON_AddItemToArray(result_array, route_obj);
        route_index++;
    }

    cJSON_Delete(json);
    return result_array;
}

char *generate_navigation_summary(cJSON *route_array)
{
    if (!cJSON_IsArray(route_array) || cJSON_GetArraySize(route_array) == 0)
    {
        return strdup("无法生成导航概要：数据格式错误或为空。");
    }

    cJSON *first_route = cJSON_GetArrayItem(route_array, 0);
    if (!cJSON_IsObject(first_route))
    {
        return strdup("无法生成导航概要：路线数据格式错误。");
    }

    char *summary = malloc(4096 * sizeof(char)); // 分配足够大的内存
    if (summary == NULL)
    {
        return strdup("内存分配失败。");
    }

    cJSON *total_distance = cJSON_GetObjectItemCaseSensitive(first_route, "total_distance");
    cJSON *total_walking_distance = cJSON_GetObjectItemCaseSensitive(first_route, "total_walking_distance");
    cJSON *segments = cJSON_GetObjectItemCaseSensitive(first_route, "segments");

    snprintf(summary, 4096, "路线生成成功，全程%s米，包含步行距离%s米。",
             total_distance->valuestring, total_walking_distance->valuestring);

    cJSON *segment = NULL;
    int segment_index = 0;
    cJSON_ArrayForEach(segment, segments)
    {
        cJSON *segment_number = cJSON_GetObjectItemCaseSensitive(segment, "segment_number");
        cJSON *walking = cJSON_GetObjectItemCaseSensitive(segment, "walking");
        cJSON *bus = cJSON_GetObjectItemCaseSensitive(segment, "bus");

        const char *conjunction = (segment_number->valueint == 1) ? "首先" : "然后";

        if (cJSON_IsObject(walking))
        {
            cJSON *walking_distance = cJSON_GetObjectItemCaseSensitive(walking, "distance");
            cJSON *walking_details = cJSON_GetObjectItemCaseSensitive(walking, "details");
            if (cJSON_IsArray(walking_details) && cJSON_GetArraySize(walking_details) > 0)
            {
                cJSON *first_detail = cJSON_GetArrayItem(walking_details, 0);
                char walking_info[256];
                snprintf(walking_info, sizeof(walking_info), "%s%s", conjunction, first_detail->valuestring);
                strcat(summary, walking_info);
            }
        }

        if (cJSON_IsObject(bus))
        {
            cJSON *bus_name = cJSON_GetObjectItemCaseSensitive(bus, "name");
            cJSON *stops_count = cJSON_GetObjectItemCaseSensitive(bus, "stops_count");
            cJSON *arrival_stop = cJSON_GetObjectItemCaseSensitive(bus, "arrival_stop");
            cJSON *duration_minutes = cJSON_GetObjectItemCaseSensitive(bus, "duration_minutes");

            char bus_info[512];
            snprintf(bus_info, sizeof(bus_info), "，乘坐%s，乘坐%d站，在%s下车，预计乘坐时间%d分钟；",
                     bus_name->valuestring, stops_count->valueint, arrival_stop->valuestring, duration_minutes->valueint);
            strcat(summary, bus_info);
        }

        segment_index++;
    }

    // 处理最后一段步行路线的详细信息
    cJSON *last_segment = cJSON_GetArrayItem(segments, cJSON_GetArraySize(segments) - 1);
    cJSON *last_walking = cJSON_GetObjectItemCaseSensitive(last_segment, "walking");
    if (cJSON_IsObject(last_walking))
    {
        cJSON *walking_details = cJSON_GetObjectItemCaseSensitive(last_walking, "details");
        if (cJSON_IsArray(walking_details))
        {
            strcat(summary, "然后");
            cJSON *detail = NULL;
            cJSON_ArrayForEach(detail, walking_details)
            {
                if (cJSON_IsString(detail))
                {
                    strcat(summary, detail->valuestring);
                    strcat(summary, "，");
                }
            }
            size_t len = strlen(summary);
            if (len > 0 && summary[len - 1] == '，')
            {
                summary[len - 1] = '\0'; // 移除最后一个逗号
            }
        }
    }

    strcat(summary, "到达目的地。");

    return summary;
}

/*
    json_str:传过来的参数
    [ 
        { 
            "city": "西安", 
            "position": "大唐芙蓉园" 
        }, 
        { 
            "city": "西安", 
            "position": "大唐不夜城" 
        }
    ]
*/

char* sum(const char *json_str)
{
    CURL *client;
    CURLcode err;
    char *response;
    size_t size;

    /*
        解析json字符串，提取出里面的四个变量
        start-city起始城市
        start-position起始地点
        destination-city目的城市
        destination-position目的地点
    */
    parse_json(json_str);

    //打印全局变量的值
    // printf("Start City: %s\n", start_city);
    // printf("Start Position: %s\n", start_position);
    // printf("Destination City: %s\n", destination_city);
    // printf("Destination Position: %s\n", destination_position);

    //获取起始地点和目的地点的坐标
    char *start_coords_response = get_coordinates(start_city, start_position);
    char *destination_coords_response = get_coordinates(destination_city, destination_position);

    if (!start_coords_response || !destination_coords_response) {
        fprintf(stderr, "Failed to get coordinates.\n");
        free(start_coords_response);
        free(destination_coords_response);
        return NULL;
    }

    char *start_location = extract_location(start_coords_response);
    char *destination_location = extract_location(destination_coords_response);

    free(start_coords_response);
    free(destination_coords_response);

    if (!start_location || !destination_location) {
        fprintf(stderr, "Failed to extract locations.\n");
        free(start_location);
        free(destination_location);
        return NULL;
    }

    //start_location起始坐标 destination_location目的地坐标
    // printf("Start Coordinates: %s\n", start_location);
    // printf("Destination Coordinates: %s\n", destination_location);

    // 创建内存流
    struct MemoryStruct chunk;
    chunk.memory = malloc(1);
    chunk.size = 0;

    // 初始化 CURL
    curl_global_init(CURL_GLOBAL_ALL);
    client = curl_easy_init();

    // 设置 CURL 选项
    char url[512];
    snprintf(url, sizeof(url), "https://restapi.amap.com/v5/direction/transit/integrated?origin=%s&destination=%s&key=c6dc687285a376347d73993a80352ff0&city1=010&city2=010&AlternativeRoute=1&show_fields=cost,arrival_stop", start_location, destination_location);
    // curl_easy_setopt(client, CURLOPT_URL, "https://restapi.amap.com/v5/direction/transit/integrated?origin=108.962723,34.278498&destination=108.993731,34.221432&key=c6dc687285a376347d73993a80352ff0&city1=010&city2=010&AlternativeRoute=1&show_fields=cost,arrival_stop");
    curl_easy_setopt(client, CURLOPT_URL, url);
    curl_easy_setopt(client, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(client, CURLOPT_WRITEDATA, (void *)&chunk);

    // 执行 CURL 请求
    err = curl_easy_perform(client);

    char *navigation_summary = NULL;

    if (err != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() 失败: %s\n", curl_easy_strerror(err));
    } else {
        // 打印公共交通路线信息（result：数组对象格式）
        cJSON *result = get_transit_route(chunk.memory, chunk.size);
        if (result != NULL) {
            // 将数组对象格式的数据转换为一段简短的导航摘要navigation_summary
            navigation_summary = generate_navigation_summary(result);
            cJSON_Delete(result);
        }
    }

    // 清理资源
    curl_easy_cleanup(client);
    free(chunk.memory);
    curl_global_cleanup();
    free(start_location);
    free(destination_location);

    return navigation_summary;
}
